//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//File  : EffectFile.fx
//Author: Robert Turner
//Date  : 2010 
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//Matricies
uniform extern float4x4 gWVP;
uniform extern float4x4 gWIT;
uniform extern float4x4 gW;

// Texture Values
uniform extern texture  gTex;
uniform extern texture  gEnviromentMap;


sampler TexS = sampler_state
{
	Texture		  = <gTex>;
	MinFilter	  = Anisotropic;
	MagFilter	  = LINEAR;
	MipFilter	  = LINEAR;
	MaxAnisotropy = 8;
	AddressU	  = WRAP;
	AddressV	  = WRAP;
};

// Material Values
uniform extern float4	gAmbientMaterial;
uniform extern float4   gDiffuseMaterial;
uniform extern float4	gSpecularMaterial;
uniform extern float	gSpecularPower; // Shininess

// Light Values
uniform extern float4	gAmbientLight;
uniform extern float4   gDiffuseLight;
uniform extern float4	gSpecularLight;
uniform extern float3   gLightVec;		// Position of the light  (world)

// Point Light
uniform extern float4	gAmbientLightPoint;
uniform extern float4   gDiffuseLightPoint;
uniform extern float4	gSpecularLightPoint;
uniform extern float3	gAttenuationPoint;   // Ambient/SpotLight: Power of the light.
uniform extern float3   gLightVecPoint;		// Position of the light  (world)

//Spot Light
uniform extern float4	gAmbientLightSpot;
uniform extern float4   gDiffuseLightSpot;
uniform extern float4	gSpecularLightSpot;
uniform extern float3	gAttenuationSpot;   // Ambient/SpotLight: Power of the light.
uniform extern float3   gLightDirection;// SpotLight: Which way the light is faceing 
uniform extern float    gSpotPower;
uniform extern float3   gLightVecSpot;		// Position of the light  (world)

// Misc Values
uniform extern float3	gEyePos;		// Position of the Camera (world)


// Struct for the output of the Vertex.
struct OutputVS
{
    float4 m_Pos     : POSITION0;
    float4 m_Diffuse : COLOR0;
    float4 m_Spec    : COLOR1;
    float2 m_Tex0    : TEXCOORD0;
};



//---------------------------------------------------------------------------------------------------------------------
// TRANSFORM SHADER:
// All this shader does is transform vertex positions.
//---------------------------------------------------------------------------------------------------------------------

OutputVS TransformVS(float3 pos : POSITION0)
{
	OutputVS outVS = (OutputVS)0;
	outVS.m_Pos    = mul(float4(pos, 1.0f), gWVP);
	
    return outVS;
}

float4 TransformPS() : COLOR
{
    return float4(0.0f, 0.0f, 0.0f, 1.0f);
}

technique TransformTech
{
    pass P0
    {
        vertexShader = compile vs_2_0 TransformVS();
        pixelShader  = compile ps_2_0 TransformPS();
		FillMode = Wireframe;
    }
}

//---------------------------------------------------------------------------------------------------------------------
// COLOR SHADER:
// This Shader can modify vertex color
//---------------------------------------------------------------------------------------------------------------------

OutputVS ColorVS(float3 pos  : POSITION0,
				 float4 color : COLOR0)
{
	OutputVS outVS  = (OutputVS)0;
	outVS.m_Pos		= mul(float4(pos, 1.0f), gWVP);
	outVS.m_Diffuse = color;
	
	return outVS;
}

float4 ColorPS(float4 color : COLOR0) : COLOR
{
	return color;
}

technique ColorTech
{
    pass P0
	{
        vertexShader = compile vs_2_0 ColorVS();
        pixelShader  = compile ps_2_0 ColorPS();
    }
}

//---------------------------------------------------------------------------------------------------------------------
// DIFFUSE LIGHT ONLY SHADER:
// This Shader displays diffuse lighting ONLY
//---------------------------------------------------------------------------------------------------------------------

OutputVS DiffuseVS(float3 pos : POSITION0, float3 norm : NORMAL0)
{
	OutputVS outVS = (OutputVS)0;
	
	//Transforms the normal vector to world space and normalizes the normal.
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm	     = normalize(worldNorm);
	
	//Lamberts Cosine Law
	//The reflected light should be most intence when the Light Vector and the Normal Vector are aligned
	//The larger the angle between them the less light hits the surface. If the angle is more that 90 degs then
	//the light does not hit the surface.
	float s             = max(dot(gLightVec, worldNorm), 0.0f);
	outVS.m_Diffuse.rgb = s*(gDiffuseMaterial * gDiffuseLight).rgb;
	outVS.m_Diffuse.a   = gDiffuseMaterial.a;
	outVS.m_Pos		    = mul(float4(pos, 1.0f), gWVP);
	
	return outVS;
}

float4 DiffusePS(float4 color : COLOR0) : COLOR
{
	return color;
}

technique DiffuseTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 DiffuseVS();
		pixelShader  = compile ps_2_0 DiffusePS();
	}
}

//---------------------------------------------------------------------------------------------------------------------
// AMBIENT/DIFFUSE LIGHT SHADER:
// This Shader displays ambient and diffuse lighting.
//---------------------------------------------------------------------------------------------------------------------

OutputVS AmbientDiffuseVS(float3 pos : POSITION0, float3 norm : NORMAL0)
{
	OutputVS outVS = (OutputVS)0;
	
	float3 worldNorm = mul(float4(norm,0.0f), gWIT).xyz;
	worldNorm        = normalize(worldNorm);
	
	float s     = max(dot(gLightVec, worldNorm), 0.0f);
	float3 diff = s*(gDiffuseMaterial * gDiffuseLight).rgb;
	float3 amb  = gAmbientMaterial * gAmbientLight;
	
	outVS.m_Diffuse.rgb = amb + diff;
	outVS.m_Diffuse.a   = gDiffuseMaterial.a;
	outVS.m_Pos		    = mul(float4(pos, 1.0f), gWVP);
	
	return outVS;
}

float4 AmbientDiffusePS(float4 color : COLOR0) : COLOR
{
	return color;
}

technique AmbientDiffuseTech
{
    pass P0
	{
        vertexShader = compile vs_2_0 AmbientDiffuseVS();
        pixelShader	 = compile ps_2_0 AmbientDiffusePS();
    }
}

//---------------------------------------------------------------------------------------------------------------------
// AMBIENT/DIFFUSE/SPECULAR LIGHT SHADER:
// This Shader displays ambient diffuse and Specular lighting.
//---------------------------------------------------------------------------------------------------------------------

OutputVS AmbientDiffuseSpecularVS(float3 pos : POSITION0, float3 norm : NORMAL0)
{
	OutputVS outVS = (OutputVS)0;
	
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm = normalize(worldNorm);
	
	float3 worldPos = mul(float4(pos, 1.0f), gW).xyz;
	
	// Vector from vertex to eye
	float3 toEye = normalize(gEyePos - worldPos);
	// Reflection vector
	float3 r     = reflect(-gLightVec, worldNorm);
	// How much specular light makes it to the eye
	float  t     = pow(max(dot(r, toEye), 0.0f), gSpecularPower);
	// Diffuse light intensity
	float  s     = max(dot(gLightVec, worldNorm),0.0f);
	
	float3 spec = t*(gSpecularMaterial * gSpecularLight).rgb;
	float3 diff = s*(gDiffuseMaterial  * gDiffuseLight).rgb;
	float3 ambi =    gAmbientMaterial  * gAmbientLight;
	
	outVS.m_Diffuse.rgb = ambi + diff + spec;
	outVS.m_Diffuse.a   = gDiffuseMaterial.a;
	outVS.m_Pos = mul(float4(pos, 1.0f), gWVP);
	
	return outVS;
}

float4 AmbientDiffuseSpecularPS(float4 color : COLOR0) : COLOR
{
	return color;
}

technique AmbientDiffuseSpecularTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 AmbientDiffuseSpecularVS();
		pixelShader  = compile ps_2_0 AmbientDiffuseSpecularPS();
	}
}

//---------------------------------------------------------------------------------------------------------------------
// POINT LIGHT SHADER:
// This Shader displays Point lighting supporting Ambient, Diffuse, and Specular light.
//---------------------------------------------------------------------------------------------------------------------

OutputVS PointLightVS(float3 pos : POSITION0, float3 norm : NORMAL0)
{
	OutputVS outVS = (OutputVS)0;
	
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm		 = normalize(worldNorm);
	float3 worldPos  = mul(float4(pos, 1.0f), gW).xyz;
	
	// Position of the Light in the World
	float3 worldLightPos = normalize(gLightVecPoint - worldPos);

	float3 ambi = (gAmbientMaterial * gAmbientLightPoint).rgb;
	
	float s	    = max(dot(worldNorm, worldLightPos), 0.0f);
	float3 diff = s*(gDiffuseMaterial * gDiffuseLightPoint).rgb;
	
	float3 toEye		= normalize(gEyePos - worldPos);
	float3 worldReflect = reflect(-worldLightPos, worldNorm);
	float t				= pow(max(dot(worldReflect, toEye), 0.0f), gSpecularPower);
	float3 spec			= t*(gSpecularMaterial * gSpecularLightPoint).rgb;
	
	float d			    = distance(gLightVecPoint ,worldPos);
	float attenuation   = gAttenuationPoint.x + gAttenuationPoint.y*d + gAttenuationPoint.z*d*d;
	
	float3 color = ambi + ((diff + spec)/attenuation);
	
	outVS.m_Diffuse = float4(color, gDiffuseMaterial.a);
	outVS.m_Pos		= mul(float4(pos, 1.0f), gWVP);
	
	return outVS;
}

float4 PointLightPS(float4 color : COLOR0) : COLOR
{
	return color;
}

technique PointLightTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 PointLightVS();
		pixelShader  = compile ps_2_0 PointLightPS();
	}
}

//---------------------------------------------------------------------------------------------------------------------
// SPOT LIGHT SHADER:
// This Shader displays a Spot light supporting Ambient, Diffuse, and Specular light.
//---------------------------------------------------------------------------------------------------------------------

OutputVS SpotLightVS(float3 pos : POSITION0, float3 norm : Normal0)
{
	OutputVS outVS = (OutputVS)0;
	
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm		 = normalize(worldNorm);
	float3 worldPos  = mul(float4(pos, 1.0f), gW).xyz;
	
	// Position of the Light in the World
	float3 worldLightPos = normalize(gLightVecSpot - worldPos);

	float3 ambi = (gAmbientMaterial * gAmbientLightSpot).rgb;
	
	float s     = max(dot(worldNorm, worldLightPos), 0.0f);
	float3 diff = s*(gDiffuseMaterial * gDiffuseLightSpot).rgb;
	
	float3 toEye        = normalize(gEyePos - worldPos);
	float3 worldReflect = reflect(-worldLightPos, worldNorm);
	float t			    = pow(max(dot(worldReflect, toEye), 0.0f), gSpecularPower);
	float3 spec			= t*(gSpecularMaterial * gSpecularLightSpot).rgb;
	
	float d			  = distance(gLightVecSpot,worldPos);
	float attenuation = gAttenuationSpot.x + gAttenuationSpot.y*d + gAttenuationSpot.z*d*d;
	
	float spot = pow(max(dot(-worldLightPos, gLightDirection), 0.0f), gSpotPower);
	
	float3 color = spot*(ambi + ((diff + spec)/attenuation));
	
	outVS.m_Diffuse = float4(color, gDiffuseMaterial.a);
	outVS.m_Pos		= mul(float4(pos, 1.0f), gWVP);
	
	return outVS;
}

float4 SpotLightPS(float4 color : COLOR0) : COLOR
{
	return color;
}

technique SpotLightTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 SpotLightVS();
		pixelShader  = compile ps_2_0 SpotLightPS();
	}
}


//---------------------------------------------------------------------------------------------------------------------
// POINT/SPOT LIGHT SHADER:
// This Shader displays a combined Point and Spot light supporting Ambient, Diffuse, and Specular light.
//---------------------------------------------------------------------------------------------------------------------

OutputVS PointSpotLightVS(float3 pos : POSITION0, float3 norm : Normal0)
{
	OutputVS outVS = (OutputVS)0;
	
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm		 = normalize(worldNorm);
	float3 worldPos  = mul(float4(pos, 1.0f), gW).xyz;
	
	///////////////////////////////////////////////////////////////////////////////////////////
	// Position of the Light in the World
	float3 worldLightPos = normalize(gLightVecPoint - worldPos);

	float3 ambi = (gAmbientMaterial * gAmbientLightPoint).rgb;
	
	float s		= max(dot(worldNorm, worldLightPos), 0.0f);
	float3 diff = s*(gDiffuseMaterial * gDiffuseLightPoint).rgb;
	
	float3 toEye		= normalize(gEyePos - worldPos);
	float3 worldReflect = reflect(-worldLightPos, worldNorm);
	float t				= pow(max(dot(worldReflect, toEye), 0.0f), gSpecularPower);
	float3 spec			= t*(gSpecularMaterial * gSpecularLightPoint).rgb;
	
	float d			  = distance(gLightVecPoint ,worldPos);
	float attenuation = gAttenuationPoint.x + gAttenuationPoint.y*d + gAttenuationPoint.z*d*d;
	
	float3 color = ambi + ((diff + spec)/attenuation);
	///////////////////////////////////////////////////////////////////////////////////////////
	
	// Position of the Light in the World
	worldLightPos = normalize(gLightVecSpot - worldPos);

	ambi = (gAmbientMaterial * gAmbientLightSpot).rgb;
	
	 s	  = max(dot(worldNorm, worldLightPos), 0.0f);
	 diff = s*(gDiffuseMaterial * gDiffuseLightSpot).rgb;
	
	 toEye		  = normalize(gEyePos - worldPos);
	 worldReflect = reflect(-worldLightPos, worldNorm);
	 t			  = pow(max(dot(worldReflect, toEye), 0.0f), gSpecularPower);
	 spec		  = t*(gSpecularMaterial * gSpecularLightSpot).rgb;
	
	 d			  = distance(gLightVecSpot,worldPos);
	 attenuation  = gAttenuationSpot.x + gAttenuationSpot.y*d + gAttenuationSpot.z*d*d;
	
	float spot = pow(max(dot(-worldLightPos, gLightDirection), 0.0f), gSpotPower);
	
	float3 color_2 = spot*(ambi + ((diff + spec)/attenuation));
	
	outVS.m_Diffuse = float4(color + color_2, gDiffuseMaterial.a);
	outVS.m_Pos		= mul(float4(pos, 1.0f), gWVP);
	
	return outVS;
}

float4 PointSpotLightPS(float4 color : COLOR0) : COLOR
{
	return color;
}

technique PointSpotLightTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 PointSpotLightVS();
		pixelShader  = compile ps_2_0 PointSpotLightPS();
	}
}

OutputVS TextureVS(float3 pos : POSITION0, float3 norm : NORMAL0, float2 tex0 : TEXCOORD0)
{
	OutputVS outVS = (OutputVS)0;
	
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm		 = normalize(worldNorm);
	float3 worldPos	 = mul(float4(pos, 1.0f), gW).xyz;
	
// Vector from vertex to eye
	float3 toEye = normalize(gEyePos - worldPos);
	// Reflection vector
	float3 r	 = reflect(-gLightVec, worldNorm);
	// How much specular light makes it to the eye
	float  t	 = pow(max(dot(r, toEye), 0.0f), gSpecularPower);
	// Diffuse light intensity
	float  s	 = max(dot(gLightVec, worldNorm),0.0f);
	
	float3 spec = t*(gSpecularMaterial * gSpecularLight).rgb;
	float3 diff = s*(gDiffuseMaterial  * gDiffuseLight).rgb;
	float3 ambi =    gAmbientMaterial  * gAmbientLight;
	
	outVS.m_Diffuse.rgb = ambi + diff;
	outVS.m_Diffuse.a   = gDiffuseMaterial.a;
	outVS.m_Spec	    = float4(spec, 0.0f);
	outVS.m_Pos		    = mul(float4(pos, 1.0f), gWVP);
	outVS.m_Tex0		= tex0;
	
	return outVS;
}


float4 TexturePS(float4 c : COLOR0, float4 spec : COLOR1, float2 tex0 : TEXCOORD0) : COLOR
{
	float4 texColor  = tex2D(TexS, tex0);
	float3  diffuse  = c.rgb *  texColor;
	
	return float4(texColor.rgb + c.rgb, c.a);
}

technique TextureTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 TextureVS();
		pixelShader  = compile ps_2_0 TexturePS();
	}
}


//TEXTURE WITH POINT LIGHT
OutputVS PointLightTextureVS(float3 pos : POSITION0, float3 norm : NORMAL0, float2 tex0 : TEXCOORD0)
{
	OutputVS outVS = (OutputVS)0;
				
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm		 = normalize(worldNorm);
	float3 worldPos  = mul(float4(pos, 1.0f), gW).xyz;

	float3 worldLightPos = normalize(gLightVecPoint - worldPos);

	float3 ambi = (gAmbientMaterial * gAmbientLightPoint).rgb;
	
	float s     = max(dot(worldNorm, worldLightPos), 0.0f);
	float3 diff = s*(gDiffuseMaterial * gDiffuseLightPoint).rgb;
	
	float3 toEye        = normalize(gEyePos - worldPos);
	float3 worldReflect = reflect(-worldLightPos, worldNorm);
	float t				= pow(max(dot(worldReflect, toEye), 0.0f), gSpecularPower);
	float3 spec			= t*(gSpecularMaterial * gSpecularLightPoint).rgb;
	
	float d			  = distance(gLightVecPoint ,worldPos);
	float attenuation = gAttenuationPoint.x + gAttenuationPoint.y*d + gAttenuationPoint.z*d*d;
	
	float3 color = ambi + (diff/attenuation);
	
	outVS.m_Diffuse = float4(color, gDiffuseMaterial.a);
	outVS.m_Spec    = float4(spec, 0.0f);
	outVS.m_Pos     = mul(float4(pos, 1.0f), gWVP);
	outVS.m_Tex0    = tex0;
	
	return outVS;
}

float4 PointLightTexturePS(float4 c : COLOR0, float4 spec : COLOR1, float2 tex0 : TEXCOORD0) : COLOR
{
	float3 texColor  = tex2D(TexS, tex0).rgb;
	float3  diffuse  = c.rgb *  texColor;
	return float4(diffuse + spec.rgb, c.a);
}

technique PointLightTextureTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 PointLightTextureVS();
		pixelShader  = compile ps_2_0 PointLightTexturePS();
		Lighting = false;
	}
}


//TEXTURE WITH SPOT LIGHT

OutputVS SpotLightTextureVS(float3 pos : POSITION0, float3 norm : NORMAL0, float2 tex0 : TEXCOORD0)
{
	OutputVS outVS = (OutputVS)0;
	
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm		 = normalize(worldNorm);
	float3 worldPos  = mul(float4(pos, 1.0f), gW).xyz;

	// Position of the Light in the World
	float3 worldLightPos = normalize(gLightVecSpot - worldPos);

	float3 ambi = (gAmbientMaterial * gAmbientLightSpot).rgb;
	
	float s		= max(dot(worldNorm, worldLightPos), 0.0f);
	float3 diff = s*(gDiffuseMaterial * gDiffuseLightSpot).rgb;
	
	float3 toEye	    = normalize(gEyePos - worldPos);
	float3 worldReflect = reflect(-worldLightPos, worldNorm);
	float t				= pow(max(dot(worldReflect, toEye), 0.0f), gSpecularPower);
	float3 spec			= t*(gSpecularMaterial * gSpecularLightSpot).rgb;
	
	float d			  = distance(gLightVecSpot,worldPos);
	float attenuation = gAttenuationSpot.x + gAttenuationSpot.y*d + gAttenuationSpot.z*d*d;
	
	float spot = pow(max(dot(-worldLightPos, gLightDirection), 0.0f), gSpotPower);
	
	float3 color = spot*(ambi + ((diff + spec)/attenuation));
	
	outVS.m_Diffuse = float4(color, gDiffuseMaterial.a);
	outVS.m_Spec	= float4(spec, 0.0f);
	outVS.m_Pos		= mul(float4(pos, 1.0f), gWVP);
	outVS.m_Tex0	= tex0;
	
	return outVS;
}

float4 SpotLightTexturePS(float4 c : COLOR0, float4 spec : COLOR1, float2 tex0 : TEXCOORD0) : COLOR
{
	float3 texColor  = tex2D(TexS, tex0).rgb;
	float3  diffuse  = c.rgb *  texColor;
	
	return float4(diffuse + spec.rgb, c.a);
	//float4 texColor = tex2D(TexS, tex0);
	//float  diffuse  = c.rgb *  texColor;
	//return float4(texColor.rgb + c.rgb, c.a);
}

technique SpotLightTextureTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 SpotLightTextureVS();
		pixelShader  = compile ps_2_0 SpotLightTexturePS();
	}
}


//////////////////////////////////////////////////////////////////////////

//TEXTURE WITH SPOT LIGHT

OutputVS PointSpotLightTextureVS(float3 pos : POSITION0, float3 norm : NORMAL0, float2 tex0 : TEXCOORD0)
{
	OutputVS outVS = (OutputVS)0;
	
	float3 worldNorm = mul(float4(norm, 0.0f), gWIT).xyz;
	worldNorm		 = normalize(worldNorm);
	float3 worldPos  = mul(float4(pos, 1.0f), gW).xyz;
////////////////////////////////////////////////////////////////////////////

	float3 worldLightPos = normalize(gLightVecPoint - worldPos);

	float3 ambi = (gAmbientMaterial * gAmbientLightPoint).rgb;
	
	float s     = max(dot(worldNorm, worldLightPos), 0.0f);
	float3 diff = s*(gDiffuseMaterial * gDiffuseLightPoint).rgb;
	
	float3 toEye        = normalize(gEyePos - worldPos);
	float3 worldReflect = reflect(-worldLightPos, worldNorm);
	float t				= pow(max(dot(worldReflect, toEye), 0.0f), gSpecularPower);
	float3 pSpec			= t*(gSpecularMaterial * gSpecularLightPoint).rgb;
	
	float d			  = distance(gLightVecPoint ,worldPos);
	float attenuation = gAttenuationPoint.x + gAttenuationPoint.y*d + gAttenuationPoint.z*d*d;
	
	float3 PointColor = ambi + (diff/attenuation);

/////////////////////////////////////////////////////////////////////////////
	// Position of the Light in the World
	 worldLightPos = normalize(gLightVecSpot - worldPos);

	 ambi = (gAmbientMaterial * gAmbientLightSpot).rgb;
	
	 s	  = max(dot(worldNorm, worldLightPos), 0.0f);
	 diff = s*(gDiffuseMaterial * gDiffuseLightSpot).rgb;
	
	 toEye	      = normalize(gEyePos - worldPos);
	 worldReflect = reflect(-worldLightPos, worldNorm);
	 t			  = pow(max(dot(worldReflect, toEye), 0.0f), gSpecularPower);
	 float3 spec  = t*(gSpecularMaterial * gSpecularLightSpot).rgb;
	
	 d			  = distance(gLightVecSpot,worldPos);
	 attenuation  = gAttenuationSpot.x + gAttenuationSpot.y*d + gAttenuationSpot.z*d*d;
	
	float spot	  = pow(max(dot(-worldLightPos, gLightDirection), 0.0f), gSpotPower);
	
	float3 color  = spot*(ambi + ((diff + spec)/attenuation));
	

	outVS.m_Diffuse = float4(PointColor + color, gDiffuseMaterial.a);
	outVS.m_Spec	= float4(pSpec + spec, 0.0f);
	outVS.m_Pos		= mul(float4(pos, 1.0f), gWVP);
	outVS.m_Tex0	= tex0;
	
	return outVS;
}

float4 PointSpotLightTexturePS(float4 c : COLOR0, float4 spec : COLOR1, float2 tex0 : TEXCOORD0) : COLOR
{
	float3 texColor  = tex2D(TexS, tex0).rgb;
	float3 diffuse  = c.rgb *  texColor;	
	return float4(diffuse + spec.rgb, c.a);
}

technique PointSpotLightTextureTech
{
	pass P0
	{
		vertexShader = compile vs_2_0 PointSpotLightTextureVS();
		pixelShader  = compile ps_2_0 PointSpotLightTexturePS();
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//PHONG LIGHTING
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct OutputVS_2
{
    float4 posH    : POSITION0;
    float3 normalW : TEXCOORD0;
    float3 toEyeW  : TEXCOORD1;
    float2 tex0    : TEXCOORD2;
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Phong Directional light
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

OutputVS_2 PhongDirLtTexVS(float3 posL : POSITION0, float3 normalL : NORMAL0, float2 tex0: TEXCOORD0)
{
    // Zero out our output.
	OutputVS_2 outVS = (OutputVS_2)0;
	
	// Transform normal to world space.
	outVS.normalW = mul(float4(normalL, 0.0f), gWIT).xyz;
	
	// Transform vertex position to world space.
	float3 posW   = mul(float4(posL, 1.0f), gW).xyz;
	
	// Compute the unit vector from the vertex to the eye.
	outVS.toEyeW  = gEyePos - posW;
	
	// Transform to homogeneous clip space.
	outVS.posH    = mul(float4(posL, 1.0f), gWVP);
	
	// Pass on texture coordinates to be interpolated in rasterization.
	outVS.tex0    = tex0;

	// Done--return the output.
    return outVS;
}

float4 PhongDirLtTexPS(float3 normalW : TEXCOORD0, float3 toEyeW  : TEXCOORD1, float2 tex0 : TEXCOORD2) : COLOR
{
	// Interpolated normals can become unnormal--so normalize.
	normalW = normalize(normalW);
	toEyeW  = normalize(toEyeW);
	
	// Light vector is opposite the direction of the light.
	float3 lightVecW = -gLightVec;
	
	// Compute the reflection vector.
	float3 r = reflect(-lightVecW, normalW);
	
	// Determine how much (if any) specular light makes it into the eye.
	float t  = pow(max(dot(r, toEyeW), 0.0f), gSpecularPower);
	
	// Determine the diffuse light intensity that strikes the vertex.
	float s = max(dot(lightVecW, normalW), 0.0f);
	
	// Compute the ambient, diffuse and specular terms separatly. 
	float3 spec    = t*(gSpecularMaterial*gSpecularLight).rgb;
	float3 diffuse = s*(gDiffuseMaterial*gDiffuseLight).rgb;
	float3 ambient = (gAmbientMaterial*gAmbientLight).rgb;
	
	// Get the texture color.
	float4 texColor = tex2D(TexS, tex0);
	
	// Combine the color from lighting with the texture color.
	float3 color = (ambient + diffuse)*texColor.rgb + spec;
		
	// Sum all the terms together and copy over the diffuse alpha.
    return float4(color, gDiffuseMaterial.a*texColor.a);
}

technique PhongDirLtTexTech
{
    pass P0
    {
        // Specify the vertex and pixel shader associated with this pass.
        vertexShader = compile vs_2_0 PhongDirLtTexVS();
        pixelShader  = compile ps_2_0 PhongDirLtTexPS();
    }
}

sampler EnvMapS = sampler_state
{
    Texture   = <gEnviromentMap>;
    MinFilter = LINEAR; 
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU  = WRAP;
    AddressV  = WRAP;
};


void SkyVS(float3 posL : POSITION0, 
           out float4 oPosH : POSITION0, 
           out float3 oEnvTex : TEXCOORD0)
{
	// Set z = w so that z/w = 1 (i.e., skydome always on far plane).
    oPosH = mul(float4(posL, 1.0f), gWVP).xyww; 
    
    // Use skymesh vertex position, in local space, as index into cubemap. 
    oEnvTex = posL;
}

float4 SkyPS(float3 envTex : TEXCOORD0) : COLOR
{
    return texCUBE(EnvMapS, envTex);
}

technique SkyBoxTech
{
    pass P0
    {
        vertexShader = compile vs_2_0 SkyVS();
        pixelShader  = compile ps_2_0 SkyPS();
		CullMode = None;
		ZFunc = Always; // Always write sky to depth buffer
		StencilEnable = true;
		StencilFunc   = Always;
		StencilPass   = Replace;
		StencilRef    = 0; // clear to zero
    }
}






//
//
//
//
////////////////////////////////////////////////
//// Glow Shader:
//// Glows are rendered as a separate pass
//// to the rest of the scene.  Glowing objects
//// get rendered to a texture, the texture is
//// blurred, then the texture is overlaid onto 
//// the main scene.
////////////////////////////////////////////////
//
//texture glowTexture;
//// texTrans is a transform used to map a 1x1 quad
//// to fill the screen.
//float4x4 texTrans : WorldProjection;
//// pSize is the pixel size of the texture,
//// equivalent to the inverse of the texture width.
//float pSize;
//
//sampler GlowSampler = sampler_state
//{
    //Texture   = (glowTexture);
    //MipFilter = LINEAR;
    //MinFilter = LINEAR;
    //MagFilter = LINEAR;
//};
//
////Passed to the vertex shader from the pipeline
//struct GLOW_INPUT
//{
	//float4 pos : POSITION;
	//float2 texCoord : TEXCOORD;
//};
//
////VS output / PS input:
//struct GLOW_OUTPUT
//{
    //float4 pos : POSITION;
    //float2 texCoord0 : TEXCOORD0;
    //float2 texCoord1 : TEXCOORD1;
    //float2 texCoord2 : TEXCOORD2;
    //float2 texCoord3 : TEXCOORD3;
//};
//
//struct TEXTURE_OUTPUT
//{
    //float4 pos : POSITION;
    //float2 texCoord0 : TEXCOORD0;
//};
////PS output:
//struct pixel
//{
	//float4 color : COLOR;
//};
//
////////////////////////////
////  Vertex Shaders:
////////////////////////////
//// These glow vertex shaders blur the texture in 
//// specific direction - up, down, left, and right.
//// They are used one after the other to obtain a full blur.
//// VS1.3 hardware could do this in 2 passes rather than 4,
//// but I only have a lowly Geforce4...
//// They work by offsetting the texture coordinates into 
//// 4 texCoord streams.  The pixel shader then reads the
//// texture color at each of these texcoords and averages them
//// together, effectively sampling a cluster of pixels.
//
//GLOW_OUTPUT glowVSHorizontal1(GLOW_INPUT IN)
//{
	//GLOW_OUTPUT OUT;
	//
	//OUT.pos =  mul(IN.pos, texTrans);
	//OUT.texCoord0 = IN.texCoord + float2(-pSize*3, 0); 
	//OUT.texCoord1 = IN.texCoord + float2(-pSize*2, 0); 
	//OUT.texCoord2 = IN.texCoord + float2(-pSize*1, 0); 
	//OUT.texCoord3 = IN.texCoord + float2(0, 0 ); 
	//
	//return OUT;
//}
//GLOW_OUTPUT glowVSHorizontal2(GLOW_INPUT IN)
//{
	//GLOW_OUTPUT OUT;
	//
	//OUT.pos =  mul(IN.pos, texTrans);
	//OUT.texCoord0 = IN.texCoord + float2(pSize*3,0); 
	//OUT.texCoord1 = IN.texCoord + float2(pSize*2, 0); 
	//OUT.texCoord2 = IN.texCoord + float2(pSize*1, 0); 
	//OUT.texCoord3 = IN.texCoord + float2(0, 0 ); 
	//
	//return OUT;
//}
//GLOW_OUTPUT glowVSVertical1(GLOW_INPUT IN)
//{
	//GLOW_OUTPUT OUT;
	//
	//OUT.pos =  mul(IN.pos, texTrans);
	//OUT.texCoord0 = IN.texCoord + float2(0,-pSize*3); 
	//OUT.texCoord1 = IN.texCoord + float2(0,-pSize*2); 
	//OUT.texCoord2 = IN.texCoord + float2(0,-pSize*1); 
	//OUT.texCoord3 = IN.texCoord + float2(0,0); 
	//
	//return OUT;
//}
//GLOW_OUTPUT glowVSVertical2(GLOW_INPUT IN)
//{
	//GLOW_OUTPUT OUT;
	//
	//OUT.pos =  mul(IN.pos, texTrans);
	//OUT.texCoord0 = IN.texCoord + float2(0,pSize*3); 
	//OUT.texCoord1 = IN.texCoord + float2(0,pSize*2);  
	//OUT.texCoord2 = IN.texCoord + float2(0,pSize*1); 
	//OUT.texCoord3 = IN.texCoord + float2(0,0);  
	//
	//return OUT;
//}
//
//
//// This is the plain vertex shader used to overlay the 
//// final glow texture over the rest of the scene.
//TEXTURE_OUTPUT outputGlowVS(GLOW_INPUT IN)
//{
	//TEXTURE_OUTPUT OUT;
	//OUT.pos =  mul(IN.pos, texTrans);
	//OUT.texCoord0 = IN.texCoord;
	//
	//return OUT;
//}
//
//
//
////////////////////////////
////  Pixel Shaders:
////////////////////////////
//
//// Add the texture values at each of the supplied texCoords
//// together, weighted by some arbitary function that gives 
//// a reasonable appearance.
//// These weights are critical to the glow behaviour,
//// and tiny changes in the values can suddenly make the glow
//// invisible or overpowering.  If anyone knows how to make this 
//// better, please let me know...
//pixel glowPS(GLOW_OUTPUT IN)
//{
	//pixel OUT;
	//float4 color = tex2D( GlowSampler, IN.texCoord0 ) * 0.1;
	//color += tex2D( GlowSampler, IN.texCoord1 ) * 0.3;
	//color += tex2D( GlowSampler, IN.texCoord2 ) * 0.4;
	//color += tex2D( GlowSampler, IN.texCoord3 ) * 0.25;
	//
	//OUT.color = color;
	//OUT.color.a = 1.0f;
	//
	//return OUT;
//}
//
//// This is the pixel shader used to overlay the final glow image
//// onto the rest of the scene.
//pixel outputGlowPS(TEXTURE_OUTPUT IN)
//{
	//pixel OUT;
	//OUT.color =  tex2D( GlowSampler, IN.texCoord0 );	
	//return OUT;
//}
//
//
////////////////////////////
////  Techniques:
////////////////////////////
//
//// Four passes blur the texture in different directions.
//// The final one overlays the texture onto the rest of 
//// the scene.
//// Annotations are used so my application can automatically
//// sort these passes into the appropriate rendering stage.
//
//technique T0
//{
	//pass P0 <string renderStage="texture";>
	//{
		//Sampler[0] = (GlowSampler);
		//vertexshader = compile vs_1_1 glowVSHorizontal1();
		//pixelshader  = compile ps_1_1 glowPS();
		//fvf = XYZ | Tex1;
	//}
	//pass P1 <string renderStage="texture";>
	//{
		//Sampler[0] = (GlowSampler);
		//vertexshader = compile vs_1_1 glowVSVertical1();
		//pixelshader  = compile ps_1_1 glowPS();
		//fvf = XYZ | Tex1;
	//}
	//pass P2 <string renderStage="texture";>
	//{
		//Sampler[0] = (GlowSampler);
		//vertexshader = compile vs_1_1 glowVSHorizontal2();
		//pixelshader  = compile ps_1_1 glowPS();
		//fvf = XYZ | Tex1;
	//}
	//pass P3 <string renderStage="texture";>
	//{
		//Sampler[0] = (GlowSampler);
		//vertexshader = compile vs_1_1 glowVSVertical2();
		//pixelshader  = compile ps_1_1 glowPS();
		//fvf = XYZ | Tex1;
	//}
//
	//pass P4 <string renderStage="post";>
	//{
		//Sampler[0] = (GlowSampler);
		//vertexshader = compile vs_1_1 outputGlowVS();
		//pixelshader  = compile ps_1_1 outputGlowPS();
		//fvf = XYZ | Tex1;
		//
		//AlphaBlendEnable = true;
		//BlendOp = Min;
		//SrcBlend = One;
		//DestBlend = One;
	//}	
//}
//